package com.cloud.cop.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
import org.springframework.util.ReflectionUtils.FieldFilter;
import org.springframework.util.ReflectionUtils.MethodCallback;
import org.springframework.util.ReflectionUtils.MethodFilter;

import com.cloud.cop.ApiMethod;
import com.cloud.cop.CopRequest;
import com.cloud.cop.CopServiceHandler;
import com.cloud.cop.CopServiceHandlerRegistry;
import com.cloud.cop.IgnoreSign;

public class DefaultCopServiceHandlerRegistry implements CopServiceHandlerRegistry {

	private Map<String,CopServiceHandler> registryMap = new HashMap<String,CopServiceHandler>();
	
	public DefaultCopServiceHandlerRegistry(ApplicationContext context){
		registerFormContext(context);
	}
	
	public void addCopServiceHandler(String methodName,
			CopServiceHandler copServiceHandler) {
		registryMap.put(methodName, copServiceHandler);
	}

	public CopServiceHandler getCopServiceHandler(String methodName) {
		return registryMap.get(methodName);
	}

	public boolean isValidMethod(String methodName) {
		return registryMap.containsKey(methodName);
	}

	//通过反射注册处理器
	public void registerFormContext(final ApplicationContext context){
		if(context==null){
			System.out.println("spring 上下文创建失败");
			return;
		}
		//获得所有的类名
		String beanNames[] = context.getBeanNamesForType(Object.class);
		for(final String beanName:beanNames){
			final Class<?> handlerType = context.getType(beanName);
			ReflectionUtils.doWithMethods(handlerType, new MethodCallback() {
				public void doWith(Method method) throws IllegalArgumentException,
						IllegalAccessException {
					//返回元素上的注解
					ApiMethod apiMethod = method.getAnnotation(ApiMethod.class);
					ReflectionUtils.makeAccessible(method);
					CopServiceHandler copServiceHandler = new CopServiceHandler();
					//设置处理的类
					copServiceHandler.setHandler(context.getBean(beanName));
					//设置处理的方法
					copServiceHandler.setMethod(method);
					//设置参数
					if(method.getParameterTypes().length>0){
						Class<?> pClass = method.getParameterTypes()[0];
						Assert.isAssignable(CopRequest.class, pClass, "参数类型必须为CopRequest类型");
						copServiceHandler.setRequestType((Class<? extends CopRequest>)pClass);
					}
					//获得不需要签名的字段
					copServiceHandler.setIgnoreSignFieldNames(getIgnoreSignFieldNames(handlerType));
					//判断是否需要session
					copServiceHandler.setNeedInSession(apiMethod.needInSession());
					//添加到注册表
					addCopServiceHandler(apiMethod.value(),copServiceHandler);
				}
			},new MethodFilter() {
				public boolean matches(Method method) {
					return method.getAnnotation(ApiMethod.class)!=null;
				}
			});
		}
		
		if(context.getParent()!=null){
			registerFormContext(context.getParent());
		}
		
	}
	
	//获得不需要签名的变量
	List<String> getIgnoreSignFieldNames(Class handlerType){
		final List<String> ignoreSignFieldNamesList = new ArrayList<String>();
		ReflectionUtils.doWithFields(handlerType, new FieldCallback() {
			
			public void doWith(Field field) throws IllegalArgumentException,
					IllegalAccessException {
				ignoreSignFieldNamesList.add(field.getName());
			}
		},new FieldFilter() {
			public boolean matches(Field field) {
				return field.getAnnotation(IgnoreSign.class)!=null;
			}
		});
		return ignoreSignFieldNamesList;
	}
}
